#pragma once 
#include<iostream>
#include<string>
#include<sys/epoll.h>
#include<unordered_map>
#include<unistd.h>
using namespace std;
class Event;
class Reactor;
typedef int (*callback_t)(Event* ev);//函数指针类型

#define SIZE 128


class Event{
  public:

    int sock;//对应的文件描述符
    string inbuffer;
    string outbuffer;//对应socket，对应的输出缓冲区

    //sock设置回调
    callback_t recver;
    callback_t sender;
    callback_t errer;
    //设置Event回指Reactor的指针
    Reactor *R;
  public:
    Event()
    {
      sock=-1;
      recver = nullptr;
      sender = nullptr;
      errer = nullptr;
      R = nullptr;
    }

    void RegisterCallback(callback_t _recver, callback_t _sender, callback_t _errer)
    {
      recver = _recver;
      sender = _sender;
      errer = _errer;
    }
    ~Event()
    {}
};

class Reactor{
  private:
    int epfd;
    unordered_map<int,Event*> events;//Epoll类管理的所有Event的集合
  public:
    Reactor():epfd(-1)
  {}

    void InitReactor()
    {
      epfd = epoll_create(SIZE);
      if(epfd<0)
      {
        cerr<<"epoll_create fail"<<endl;
        exit(2);
      }
      cout<<"InitReactor success"<<endl;
    }
    bool InsertEvent(Event *evp, uint32_t evs)
    {
      //1. 将sock中的sock插入到epoll里
      struct epoll_event ev;
      ev.events = evs;
      ev.data.fd = evp->sock;
      if(epoll_ctl(epfd,EPOLL_CTL_ADD,evp->sock,&ev)<0)
      {
        cerr<<"epoll_ctl add event failed"<<endl;
        return false;
      }
      //2.将ev本身插入到unordered_map中
      events.insert({evp->sock,evp});
    }
    void DeleteEvent(Event* evp)
    {
      int sock = evp->sock;
      auto iter = events.find(sock);
      if(iter!=events.end())
      {
        //1.将sock中的sock从epoll中删除它        
        epoll_ctl(epfd,EPOLL_CTL_DEL,sock,nullptr);
        //2。将特定的ev从unordered_map中移除
        events.erase(iter);
        //3.close
        close(sock);
        //4.删除event节点
        delete evp;
      }
    }

    //使能读写
    bool EnableRW(int sock,bool read,bool write)
    {
      struct epoll_event ev;
      ev.events = EPOLLET|(read?EPOLLIN:0)|(write?EPOLLOUT:0);
      ev.data.fd = sock;
      if(epoll_ctl(epfd,EPOLL_CTL_MOD,sock,&ev)<0)
      {
        cerr<<"epoll_ctl add event failed"<<endl;
        return false;
      }

    }

    bool IsSockOk(int sock)
    {
      auto iter  = events.find(sock);
      return iter!=events.end();
    }
    //就绪事件的派发器逻辑
    void Dispatcher(int timeout)
    {
      struct epoll_event revs[SIZE];
      int n= epoll_wait(epfd,revs,SIZE,timeout);
      for(int i= 0;i<n;i++)
      {
        int sock =revs[i].data.fd;
        uint32_t revent = revs[i].events;
        //代表差错处理，将所有的错误问题全部转化成IO函数去解决
        if(revent&EPOLLERR) revent|=(EPOLLIN|EPOLLOUT);
        if(revent&EPOLLHUP) revent|=(EPOLLIN|EPOLLOUT);
        //读事件就绪
        if(revent&EPOLLIN) 
        {
          //直接调用回调的方法读取
          if((IsSockOk(sock))&&events[sock]->recver)  events[sock]->recver(events[sock]);
        }
        if(revent&EPOLLOUT)
        {
          if((IsSockOk(sock))&&events[sock]->sender)  events[sock]->sender(events[sock]);
        }

      }
    }
    ~Reactor(){} 

};

